package org.wattdepot.cli;

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClientException;
import org.wattdepot.resource.source.jaxb.Source;

/**
 * Executes the totalpower command.
 * 
 * @author Scott Wong and Kelli Sawai
 * 
 */
public class TotalPower extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Executes and returns the results of the totalpower command.
   * 
   * @param args The arguments required to execute this method.
   * @return The results of the command.
   */
  public String doCommand(String args) {
    try {
      if (args.matches("totalpower \\w* \\S* fueltype \\w*")) {
        String[] temp = args.split("\\s");
        XMLGregorianCalendar date = toTimestamp(temp[2]);
        // Check if the timestamp is in the future.
        XMLGregorianCalendar now =
            DatatypeFactory.newInstance()
                .newXMLGregorianCalendar(new GregorianCalendar());
        if (date.compare(now) >= 0) {
          return futureTimestampMessage;
        }
        String plants = getRelatedPlants(temp[1]);

        // if the plant is not a parent plant.
        if (plants.compareToIgnoreCase("none") == 0) {
          return listTotalPower(temp[1], date);
        }
        // if the plant is a parent plant
        else {
          String[] holder = plants.split(", ");
          double total = 0;

          // adds up all the power from the subsources
          for (int i = 0; i < holder.length; i++) {
            Source source = client.getSource(holder[i]);

            // only adds power to the total if the energy type matches the type requested
            if (temp[4].compareTo(source.getProperty("fuelType")) == 0) {
              total += Double.parseDouble(listTotalPower(holder[i], date));
            }
          }
          return Double.toString(total);
        }
      }
      else {
        return "The command you have entered is invalid.";
      }
    }
    catch (ResourceNotFoundException e) {
      return resourceMessage;
    }
    catch (WattDepotClientException e) {
      return "An error occured while executing the requested command.";
    }
    catch (Exception e) {
      return "An error occured while executing the requested command.";
    }
  }

  /**
   * Returns the total amount of power generated by this source for the given day.
   * 
   * @param src The source.
   * @param day The day.
   * @return String of carbon or energy generated.
   * @throws WattDepotClientException if an error occurs.
   */
  private String listTotalPower(String src, XMLGregorianCalendar day)
      throws WattDepotClientException {

    try {
      return Double.toString(client.getPowerGenerated(src, day));
    }
    catch (ResourceNotFoundException e) {
      return resourceMessage;
    }
  }

  /**
   * Determines if the source plant is associated with any other plants.
   * 
   * @param src The main plant.
   * @return The plants associated with the source plant.
   * @throws NotAuthorizedException If the user is not authorized to access the data.
   * @throws ResourceNotFoundException If the date requested isn't found.
   * @throws BadXmlException If the xml is bad.
   * @throws MiscClientException If an error occurs.
   */
  private String getRelatedPlants(String src) throws NotAuthorizedException,
      ResourceNotFoundException, BadXmlException, MiscClientException {
    /** Default for variable. */
    String none = "none";
    Source source;
    try {
      source = client.getSource(src);
    }
    catch (NotAuthorizedException e) {
      return notAuthorizedMessage;
    }
    catch (ResourceNotFoundException e) {
      return resourceMessage;
    }
    catch (BadXmlException e) {
      e.printStackTrace();
      return "Error: Bad XML";
    }
    catch (MiscClientException e) {
      e.printStackTrace();
      return "An error occured";
    }

    // Sources subSources
    String subSources = none;

    // saves all of the source's subsources to a string.
    if (!(source.getSubSources() == null)) {
      subSources = source.getSubSources().toString();
      subSources = subSources.replace("[", "");
      subSources =
          subSources.replace("http://server.wattdepot.org:8182/wattdepot/sources/", "");
      subSources = subSources.replace("]", "");
    }

    return subSources;
  }
}
